using MicroMsg.Common.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace MicroMsg.Storage
{
	public class StorageMemory<T, TKey> : IStorageLogin where T : StorageItem
	{
		private const string TAG = "StorageMemory";
		public const int ON_ITEM_ADD = 0;
		public const int ON_ITEM_DEL = 1;
		public const int ON_ITEM_MOD = 2;
		private Dictionary<TKey, T> mapItem;
		private Func<T, TKey> getKey;
		private StorageTable<T, TKey> storage;
		private bool bInit;
		public StorageMemory(Expression<Func<T, TKey>> keySelector)
		{
			this.getKey = keySelector.Compile();
			this.storage = new StorageTable<T, TKey>(keySelector);
			StorageBasic.registerLoginNotify(this);
		}
		public virtual void onLogin(string userName)
		{
		}
		public virtual void onLogout()
		{
			this.uninit();
		}
		protected virtual bool init()
		{
			if (!this.storage.isReady())
			{
				return false;
			}
			if (this.bInit)
			{
				DebugEx.debugBreak();
			}
			this.bInit = true;
			this.storage.getList();
			this.mapItem = Enumerable.ToDictionary<T, TKey>(this.storage.getList(), this.getKey);
			return true;
		}
		protected virtual void uninit()
		{
			this.bInit = false;
		}
		public bool isReady()
		{
			if (!this.bInit)
			{
				this.init();
			}
			return this.bInit && this.storage.isReady();
		}
		public virtual bool check(T item)
		{
			return item != null && this.valid(this.getKey.Invoke(item));
		}
		protected bool valid(object param)
		{
			return param != null && (!(param is string) || !string.IsNullOrEmpty(param as string));
		}
		public int count()
		{
			if (!this.isReady())
			{
				return 0;
			}
			return Enumerable.Count<KeyValuePair<TKey, T>>(this.mapItem);
		}
		public T method_0(TKey gparam_0)
		{
			if (gparam_0 == null || !this.isReady())
			{
				return default(T);
			}
			if (!this.mapItem.ContainsKey(gparam_0))
			{
				return default(T);
			}
			return this.mapItem.get_Item(gparam_0);
		}
		protected T method_1(Func<T, bool> predicate)
		{
			if (predicate != null && this.isReady())
			{
				return Enumerable.FirstOrDefault<T>(Enumerable.Where<T>(Enumerable.ToList<T>(Enumerable.Select<KeyValuePair<TKey, T>, T>(this.mapItem, (KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value())), predicate));
			}
			return default(T);
		}
		public List<T> getList()
		{
			if (!this.isReady())
			{
				return null;
			}
			return Enumerable.ToList<T>(Enumerable.Select<KeyValuePair<TKey, T>, T>(this.mapItem, (KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value()));
		}
		public List<T> getList(List<TKey> keyList)
		{
			if (keyList != null && keyList.get_Count() > 0 && this.isReady())
			{
				List<T> list = new List<T>();
				using (List<TKey>.Enumerator enumerator = keyList.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						TKey current = enumerator.get_Current();
						if (this.mapItem.ContainsKey(current))
						{
							list.Add(this.mapItem.get_Item(current));
						}
					}
				}
				return list;
			}
			return null;
		}
		protected List<T> search(Func<T, bool> predicate = null, int start = -1, int int_0 = -1)
		{
			if (!this.isReady())
			{
				return null;
			}
			if (predicate == null)
			{
				if (start < 0)
				{
					return Enumerable.ToList<T>(Enumerable.Select<KeyValuePair<TKey, T>, T>(this.mapItem, (KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value()));
				}
				return Enumerable.ToList<T>(Enumerable.Take<T>(Enumerable.Skip<T>(Enumerable.ToList<T>(Enumerable.Select<KeyValuePair<TKey, T>, T>(this.mapItem, (KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value())), start), int_0));
			}
			else
			{
				if (start < 0)
				{
					return Enumerable.ToList<T>(Enumerable.Where<T>(Enumerable.ToList<T>(Enumerable.Select<KeyValuePair<TKey, T>, T>(this.mapItem, (KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value())), predicate));
				}
				return Enumerable.ToList<T>(Enumerable.Take<T>(Enumerable.Skip<T>(Enumerable.Where<T>(Enumerable.Select<KeyValuePair<TKey, T>, T>(this.mapItem, (KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value()), predicate), start), int_0));
			}
		}
		protected List<T> getList(Func<T, bool> predicate)
		{
			if (predicate == null)
			{
				return null;
			}
			return this.search(predicate, -1, -1);
		}
		protected List<T> getList(Func<T, bool> predicate, int start, int int_0)
		{
			if (predicate != null && start >= 0 && int_0 > 0)
			{
				return this.search(predicate, start, int_0);
			}
			return null;
		}
		protected List<T> getOrderList<PKey>(Func<T, PKey> keySelector, int start, int int_0)
		{
			Func<KeyValuePair<TKey, T>, T> func = null;
			if (!this.isReady())
			{
				return null;
			}
			try
			{
				IEnumerable<KeyValuePair<TKey, T>> arg_23_0 = this.mapItem;
				if (func == null)
				{
					func = ((KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value());
				}
				return Enumerable.ToList<T>(Enumerable.Take<T>(Enumerable.Skip<T>(Enumerable.OrderBy<T, PKey>(Enumerable.Select<KeyValuePair<TKey, T>, T>(arg_23_0, func), keySelector), start), int_0));
			}
			catch (Exception ex)
			{
				Log.smethod_1("StorageMemory", " getOrderList exception" + ex);
				DebugEx.debugBreak();
			}
			return null;
		}
		public virtual bool vmethod_0(T item)
		{
			if (!this.check(item) || !this.isReady())
			{
				return false;
			}
			TKey tKey = this.getKey.Invoke(item);
			if (this.mapItem.ContainsKey(tKey))
			{
				return false;
			}
			this.mapItem.set_Item(tKey, item);
			this.syncNotify(0, item, true);
			return true;
		}
		public bool addList(List<T> itemList)
		{
			if (itemList != null && itemList.get_Count() > 0 && this.isReady())
			{
				using (List<T>.Enumerator enumerator = itemList.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						T current = enumerator.get_Current();
						this.vmethod_0(current);
					}
				}
				return true;
			}
			return false;
		}
		public bool method_2(T item)
		{
			if (!this.check(item) || !this.isReady())
			{
				return false;
			}
			TKey tKey = this.getKey.Invoke(item);
			if (!this.mapItem.ContainsKey(tKey))
			{
				return true;
			}
			this.syncNotify(1, this.mapItem.get_Item(tKey), true);
			this.mapItem.Remove(tKey);
			return true;
		}
		public bool method_3(TKey gparam_0)
		{
			if (gparam_0 == null || !this.isReady())
			{
				return false;
			}
			if (!this.mapItem.ContainsKey(gparam_0))
			{
				return true;
			}
			this.syncNotify(1, this.mapItem.get_Item(gparam_0), true);
			this.mapItem.Remove(gparam_0);
			return true;
		}
		protected bool method_4(Func<T, bool> predicate)
		{
			if (predicate != null && this.isReady())
			{
				List<T> list = Enumerable.ToList<T>(Enumerable.Where<T>(Enumerable.ToList<T>(Enumerable.Select<KeyValuePair<TKey, T>, T>(this.mapItem, (KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value())), predicate));
				using (List<T>.Enumerator enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						T current = enumerator.get_Current();
						this.syncNotify(1, current, true);
						this.mapItem.Remove(this.getKey.Invoke(current));
					}
				}
				return true;
			}
			return false;
		}
		public bool delList(List<T> itemList)
		{
			if (itemList != null && itemList.get_Count() > 0 && this.isReady())
			{
				using (List<T>.Enumerator enumerator = itemList.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						T current = enumerator.get_Current();
						this.method_2(current);
					}
				}
				return true;
			}
			return false;
		}
		public void clear(bool bNotify = false)
		{
			if (!this.isReady())
			{
				return;
			}
			using (Dictionary<TKey, T>.Enumerator enumerator = this.mapItem.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					KeyValuePair<TKey, T> current = enumerator.get_Current();
					this.syncNotify(1, current.get_Value(), bNotify);
				}
			}
			this.mapItem.Clear();
		}
		public bool modify(T item)
		{
			if (!this.check(item) || !this.isReady())
			{
				return false;
			}
			TKey tKey = this.getKey.Invoke(item);
			if (!this.mapItem.ContainsKey(tKey))
			{
				DebugEx.debugBreak();
				return false;
			}
			this.syncNotify(2, item, true);
			return true;
		}
		public bool update(T item)
		{
			if (this.check(item) && this.isReady())
			{
				TKey tKey = this.getKey.Invoke(item);
				if (this.mapItem.ContainsKey(tKey))
				{
					T t = this.mapItem.get_Item(tKey);
					if (t != item)
					{
						t.merge(item);
						t.modify = item.modify;
					}
					this.syncNotify(2, t, true);
				}
				else
				{
					this.mapItem.set_Item(tKey, item);
					this.syncNotify(0, item, true);
				}
				return true;
			}
			return false;
		}
		protected bool update(T item, Func<T, bool> func_0)
		{
			if (!this.isReady())
			{
				return false;
			}
			T t = Enumerable.FirstOrDefault<T>(Enumerable.Where<T>(Enumerable.ToList<T>(Enumerable.Select<KeyValuePair<TKey, T>, T>(this.mapItem, (KeyValuePair<TKey, T> keyValuePair_0) => keyValuePair_0.get_Value())), func_0));
			if (t != null)
			{
				if (t != item)
				{
					t.merge(item);
					t.modify = item.modify;
				}
				this.syncNotify(2, t, true);
				return true;
			}
			return this.vmethod_0(item);
		}
		public bool updateList(List<T> itemList)
		{
			if (itemList != null && itemList.get_Count() > 0 && this.isReady())
			{
				using (List<T>.Enumerator enumerator = itemList.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						T current = enumerator.get_Current();
						TKey tKey = this.getKey.Invoke(current);
						if (this.mapItem.ContainsKey(tKey))
						{
							this.mapItem.get_Item(tKey).modify = 0L;
						}
					}
				}
				using (List<T>.Enumerator enumerator2 = itemList.GetEnumerator())
				{
					while (enumerator2.MoveNext())
					{
						T current2 = enumerator2.get_Current();
						TKey tKey2 = this.getKey.Invoke(current2);
						if (this.mapItem.ContainsKey(tKey2))
						{
							T t = this.mapItem.get_Item(tKey2);
							t.merge(current2);
							t.modify |= current2.modify;
							this.syncNotify(2, t, true);
						}
						else
						{
							this.mapItem.set_Item(tKey2, current2);
							this.syncNotify(0, current2, true);
						}
					}
				}
				return true;
			}
			return false;
		}
		public void syncNotify(int operation, T item, bool bNotify = true)
		{
			this.storage.dataChangeRequest((DataOper)operation, item.clone<T>());
			if (bNotify)
			{
				this.notify(operation, item);
			}
		}
		public virtual void notify(int operation, T item)
		{
		}
		public void dumpTable()
		{
			if (this.mapItem != null && this.isReady())
			{
				using (Dictionary<TKey, T>.Enumerator enumerator = this.mapItem.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						KeyValuePair<TKey, T> arg_26_0 = enumerator.get_Current();
					}
				}
				return;
			}
		}
		public int setFlushCompleteHandler(Action Flushcomplete)
		{
			return this.storage.setFlushCompleteHandler(Flushcomplete);
		}
	}
}
